/*******************************************************************************
 * Copyright (C) 2010 Chris Wroe
 * 
 * Modifications to the initial code base are copyright of their respective
 * authors, or their employers as appropriate.
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307
 ******************************************************************************/

package uk.co.wroedevelopments.semanticworkbench.testutils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.internal.utils.FileUtil;
import org.neo4j.api.core.NeoService;
import org.neo4j.api.core.Node;
import org.neo4j.api.core.Transaction;
import org.neo4j.impl.util.FileUtils;
import org.neo4j.util.index.LuceneIndexService;
import org.xtext.example.semDsl.Concept;
import org.xtext.example.semDsl.SemDslFactory;

import uk.co.wroedevelopments.semanticworkbench.store.Connection;
import uk.co.wroedevelopments.semanticworkbench.store.KnowledgeBaseStore;
import uk.co.wroedevelopments.semanticworkbench.store.NodeConstants;
import uk.co.wroedevelopments.semanticworkbench.store.NodePropertyType;

public class NeoStoreFixture {
	NeoService connection = null;
	LuceneIndexService index = null;
	final public static String Store_Location = "../NeoTestStore";
	
	public  NeoService startService(String testStore) {
		connection = Connection.startService(testStore);
		index = Connection.getIndexService();
		initStore(connection);
		return connection;
	}
	
	public Concept getTestConcept(String name) {
		Concept c = SemDslFactory.eINSTANCE.createConcept();
		c.setName("TestConcept");
		return c;
	}
	
	
	private void initStore(NeoService conn) {
		Node result = null;
		Transaction tx = conn.beginTx();
		
		try {
		createTopNode(conn,NodeConstants.TOP_CONCEPT);
		createTopNode(conn,NodeConstants.TOP_ATTRIBUTE);
		createTopNode(conn,NodeConstants.TOP_RESTRICTION);
		createTopNode(conn,NodeConstants.TOP_CONCEPT_INCLUSION_AXIOM);
		createTopNode(conn,NodeConstants.TOP_CONJUNCTION_AXIOM);
		createTopNode(conn,NodeConstants.TOP_ROLE_INCLUSION_AXIOM);
		createTopNode(conn,NodeConstants.TOP_POSITIVE_EXISTENTIAL_AXIOM);
		createTopNode(conn,NodeConstants.TOP_NEGATIVE_EXISTENTIAL_AXIOM);
		
		tx.success();
		
		
		}
		finally {
			tx.finish();
		}
		
	}

	private void createTopNode(NeoService conn, NodeConstants topNodeType) {
		Node result;
		result = conn.createNode();
		result.setProperty(NodePropertyType.NAME.name(), topNodeType.name());
		index.index(result, NodePropertyType.NAME.name(), topNodeType.name());
	}

	public void stopService() throws Exception {
		Connection.stopService();
		File f = new File(Store_Location);
		if (!f.isDirectory()) throw new Exception("no neo directory");
		recursiveDelete(f); 
		
		
	}

	public NeoService getConnection() throws Exception {
		if (connection==null) throw new Exception("Neo Connection not set up");
		return connection;
	}

	public LuceneIndexService getIndex() throws Exception {
		if (index==null) throw new Exception("Neo Index not set up");
		return index;
	}
	
	public List<String> getNodeCount() {
		int count = 0;
		List<String> nodeNames = new ArrayList<String>();
		Transaction tx = connection.beginTx();
		try {
			
			for (Node n : connection.getAllNodes()) {
				if (n.hasProperty(NodePropertyType.NAME.name())) {
				nodeNames.add((String) n.getProperty(NodePropertyType.NAME.name()));
				}
				else 
				{
					nodeNames.add("unknown");
				}
			};
			tx.success();
		}
		finally
		{
			tx.finish();
		}
		return nodeNames;
	}
	
	public static void recursiveDelete(File f) {
		for (File g :f.listFiles()) {
			if (g.isDirectory()) recursiveDelete(g);
			g.delete();
		}
	}
	

}
